﻿/*************************************************************************
*    Taken from http://msdn.microsoft.com/en-us/library/ms748978.aspx    *   
*                                                                        *
*                                                                        *
************************************************************************/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace RSSFeedReader.Controls
{
    /// <summary>
    /// Inherits from TextBox
    /// </summary>
    public class CommandTextBox : TextBox, ICommandSource
    {

        #region ICommandSource Members
        // ICommand Interface Memembers
        /// <summary>
        /// Make Command a dependency property so it can use databinding.
        /// </summary>
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register(
                "Command",
                typeof(ICommand),
                typeof(CommandTextBox),
                new PropertyMetadata((ICommand)null,
                new PropertyChangedCallback(CommandChanged)));

        /// <summary>
        /// 
        /// </summary>
        public ICommand Command
        {
            get
            {
                return (ICommand)GetValue(CommandProperty);
            }
            set
            {
                SetValue(CommandProperty, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register(
                "CommandTarget",
                typeof(IInputElement),
                typeof(CommandTextBox),
                new PropertyMetadata((IInputElement)null));

        /// <summary>
        /// 
        /// </summary>
        public IInputElement CommandTarget
        {
            get
            {
                return (IInputElement)GetValue(CommandTargetProperty);
            }
            set
            {
                SetValue(CommandTargetProperty, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty =
           DependencyProperty.Register(
               "CommandParameter",
               typeof(object),
               typeof(CommandTextBox),
               new PropertyMetadata((object)null));

        /// <summary>
        /// 
        /// </summary>
        public object CommandParameter
        {
            get
            {
                return (object)GetValue(CommandParameterProperty);
            }
            set
            {
                SetValue(CommandParameterProperty, value);
            }
        }
        #endregion

        #region Private Methods
        // Command dependency property change callback.
        private static void CommandChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            CommandTextBox cs = (CommandTextBox)d;
            cs.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
        }
        // Add a new command to the Command Property.
        private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
        {
            // If oldCommand is not null, then we need to remove the handlers.
            if (oldCommand != null)
            {
                RemoveCommand(oldCommand, newCommand);
            }
            AddCommand(oldCommand, newCommand);
        }

        // Remove an old command from the Command Property.
        private void RemoveCommand(ICommand oldCommand, ICommand newCommand)
        {
            EventHandler handler = CanExecuteChanged;
            oldCommand.CanExecuteChanged -= handler;
        }

        // Add the command.
        private void AddCommand(ICommand oldCommand, ICommand newCommand)
        {
            EventHandler handler = new EventHandler(CanExecuteChanged);
            canExecuteChangedHandler = handler;
            if (newCommand != null)
            {
                newCommand.CanExecuteChanged += canExecuteChangedHandler;
            }
        }

        // Event handler for when the CanExecute event changes
        private void CanExecuteChanged(object sender, EventArgs e)
        {
            if (Command != null)
            {
                RoutedCommand command = Command as RoutedCommand;

                // If a RoutedCommand.
                if (command != null)
                {
                    if (command.CanExecute(CommandParameter, CommandTarget))
                    {
                        IsEnabled = true;
                    }
                    else
                    {
                        // Comment out as we do not want to disable the textbox
                        //IsEnabled = false;
                    }
                }
                // If a not RoutedCommand.
                else
                {
                    if (Command.CanExecute(CommandParameter))
                    {
                        IsEnabled = true;
                        ((ICommand)Command).Execute(CommandParameter);
                    }
                    else
                    {
                        // Comment out as we do not want to disable the textbox
                        //IsEnabled = false;
                    }
                }
            }
        }
        #endregion

        #region Override Methods
        /// <summary>
        ///Override OnGotFocus so that we will execute the command when the textbox has focus.
        /// </summary>
        /// <param name="e">Event arguments describing the event.</param>
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);

            if (Command != null)
            {
                RoutedCommand command = Command as RoutedCommand;

                if (command != null)
                {
                    command.Execute(CommandParameter, CommandTarget);
                }
                else
                {
                    ((ICommand)Command).Execute(CommandParameter);
                }
            }
        }
        #endregion

        // Keep a copy of the handler so it doesn't get garbage collected.
        private static EventHandler canExecuteChangedHandler;
    }
}
